package com.hmdp.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

public class RedisCache {

    private static TimeUnit CACHE_NULL_TIMEUNIT = TimeUnit.SECONDS;
    private static long CACHE_NULL_TIME = 60;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 将对象保存到redis中的String
     *
     * @param key
     * @param data
     */
    public void setCache(String key, Object data) {
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        valueOperations.set(key, JSONUtil.toJsonStr(data));
    }

    /**
     * 保存对象到redis中的String，带逻辑过期
     *
     * @param key
     * @param data
     * @param time
     * @param timeUnit
     */
    public void setWithLogicalExpire(String key, Object data, Long time, TimeUnit timeUnit) {
        RedisData redisData = RedisData.builder()
                .data(data)
                .expireTime(LocalDateTime.now().plusSeconds(timeUnit.toSeconds(time)))
                .build();
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));
    }

    /**
     * 根据key获取redis中string类型的值，缓存穿透策略是空值
     * 当缓存中没有，就去数据库中查找
     * @param key
     * @param clazz
     * @param supplier 从数据库中查找，返回一个数据
     * @return
     * @param <T>
     */
    public <T> T getCache(String key, Class<T> clazz, Supplier<T> supplier) {
        String jsonData = stringRedisTemplate.opsForValue().get(key);
        if (jsonData == null) {
            T sqlData = supplier.get();
            //插入空值防止缓存穿透
            if (sqlData == null) {
                stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TIME, CACHE_NULL_TIMEUNIT);
                return null;
            }
            return sqlData;
        }
        if ("".equals(jsonData)) {
            return null;
        }
        return JSONUtil.toBean(jsonData, clazz);
    }

    public static TimeUnit getCacheNullTimeunit() {
        return CACHE_NULL_TIMEUNIT;
    }

    public static void setCacheNullTimeunit(TimeUnit cacheNullTimeunit) {
        CACHE_NULL_TIMEUNIT = cacheNullTimeunit;
    }

    public static long getCacheNullTime() {
        return CACHE_NULL_TIME;
    }

    public static void setCacheNullTime(long cacheNullTime) {
        CACHE_NULL_TIME = cacheNullTime;
    }


}
